Skip to content

pwd: fix hostname resolution on macos #7029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

reykjalin
Copy link
Contributor

Note

This is still a draft. The problem is tedious to reproduce, but this should fix it. Once I've confirmed that this addresses the issue I'll clean up the PR and mark it as a non-draft

Description

Yet another edge case in #2484

When macOS's "Private WiFi address" feature is enabled it'll change the hostname to a mac address. Mac addresses look like URIs with a hostname and port component, e.g. 12:34:56:78:90:12 where :12 looks like port 12. However, mac addresses use hex numbers and as such can also contain letters a through f. So, a mac address like ab:cd:ef:ab:cd:ef is valid, but will not be parsed as a URI, because :ef is not a valid port.

This commit attempts to fix that by checking if the hostname is a valid mac address when std.Uri.parse() fails and constructing a new std.Uri struct using that information.

It's not perfect, but is equally compliant with the URI spec as std.Uri currently is. Meaning not at all compliant 😅

Testing instructions

Important

You must be connected to WiFi to be able to test this.

Setup - Enable the "Private WiFi address" setting

  1. Open your mac's "System Settings".
  2. Go to Network → Wi-Fi → Details.
image
  1. Set the "Private Wi-Fi address" setting to Rotating.
image

Important

Now you wait. The private Wi-Fi address will eventually rotate to a mac address that ends with a non-digit, e.g. 0a, ff, e2, etc. You'll notice this when your shell integration stops working, e.g. you open a new tab in Ghostty and the shell is in your home directory instead of whichever directory you had open in your previous tab.

Testing the changes

  1. Open Ghostty.
  2. cd to any directory that isn't the default (usually $HOME) directory, e.g. cd Documents.
  3. Open a new tab (Cmd+T) or split (Cmd+D).
  4. Assuming the setup steps have been followed you should:
    • On main: land in $HOME in the new tab or split.
    • On this branch: land in the same working directory as the original tab or split.

When macOS's "Private WiFi address" feature is enabled it'll change the
hostname to a mac address. Mac addresses look like URIs with a hostname
and port component, e.g. 12:34:56:78:90:12 where `:12` looks like port
12. However, mac addresses can also contain letters a through f, so a
valid mac address like ab:cd:ef:ab:cd:ef is valid, but will not be parsed
as a URI, because `:ef` is not a valid port.

This commit attempts to fix that by checking if the hostname is a valid
mac address when `std.Uri.parse()` fails and constructing a new std.Uri
struct using that information.

It's not perfect, but is equally compliant with the URI spec as std.Uri
currently is.
Copy link
Collaborator

@jparise jparise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two quick thoughts:

  1. This is probably getting complicated enough to warrant a separate utility function (with tests), perhaps outside of the stream handler.
  2. I'm starting to feel like we should follow Kitty's example and treat the file:// and kitty-report-cwd:// schemes differently: only file:// URLs get the encoding. (See elvish: use kitty-shell-cwd:// to report pwd #7033)

@reykjalin
Copy link
Contributor Author

This is probably getting complicated enough to warrant a separate utility function (with tests), perhaps outside of the stream handler.

100% agree, I had the same thought as I was working on this. I haven't confirmed the fix though so I figured I'd make a quick and dirty version that I could test, and clean it up later. And yep, that includes a separate function, tests, the whole thing 🙂

I'm starting to feel like we should follow Kitty's example and treat the file:// and kitty-report-cwd:// schemes differently: only file:// URLs get the encoding.

Yeah, we probably should. Or at the very least we probably shouldn't be using std.Uri here. It's such an incomplete implementation at this point that we'd probably be better served making our own parser here 🤔

For example, percent_encoding isn't actually enforced in std.Uri, it just assumes it. There's no escaping or cleaning done to the path to make sure it's safe, etc. That shouldn't necessarily be part of std.Uri, but I think those are things we should be doing here, so we'll want our own parser here eventually anyway 🤔

@jcollie
Copy link
Member

jcollie commented Apr 8, 2025

It seems to me that this would be better solved on the macOS level. Either by using scutil to force a "real" hostname or modifying the shell integration to inject a better hostname into the OSC 7 escape.

@reykjalin
Copy link
Contributor Author

It seems to me that this would be better solved on the macOS level. Either by using scutil to force a "real" hostname or modifying the shell integration to inject a better hostname into the OSC 7 escape.

I think the main problem is that posix.gethostname() - the hostname we compare to whatever the shell integration passes to us - returns the mac address version of the hostname.

I suppose we could run scutil --get LocalHostName on macOS instead of calling posix.gethostname() and make sure the shell integration is getting a similar value for us to compare 🤔
But it also feels really bad to have to run an external executable on macOS to get this working right.

And either way I think we should treat mac addresses as valid hostnames, even if they're not compliant with the general linux hostname spec of [a-z0-9] and a hyphen (-) due to using colons (:). This feature is enabled by default in macOS, and it isn't that big of a lift to support specifically only valid mac addresses, even if it does complicate this particular part of the codebase somewhat.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants